package com.hbk.service.impl;

import com.baomidou.mybatisplus.core.incrementer.DefaultIdentifierGenerator;
import com.hbk.base.common.CommonResult;
import com.hbk.base.common.DataGrid;
import com.hbk.base.common.Ref;
import com.hbk.base.component.EnvPostProcessor;
import com.hbk.base.component.ExternalConfig;
import com.hbk.base.util.Md5Util;
import com.hbk.base.util.ServletUtil;
import com.hbk.base.util.StringUtil;
import com.hbk.base.util.TimeUtil;
import com.hbk.entity.News;
import com.hbk.entity.NewsAttachment;
import com.hbk.entity.NewsContent;
import com.hbk.mapper.NewsAttachmentMapper;
import com.hbk.mapper.NewsContentMapper;
import com.hbk.mapper.NewsMapper;
import com.hbk.param.NewsParam;
import com.hbk.service.ICacheService;
import com.hbk.service.INewsService;
import com.hbk.service.IOssService;
import com.hbk.vo.NewsVo;
import org.jsoup.Jsoup;
import org.jsoup.nodes.Document;
import org.jsoup.nodes.Element;
import org.jsoup.select.Elements;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import java.io.File;
import java.io.IOException;
import java.time.LocalDate;
import java.util.*;

@Service
@Transactional
public class NewsServiceImpl implements INewsService {

    @Resource
    private NewsMapper newsMapper;
    @Resource
    private NewsContentMapper newsContentMapper;
    @Resource
    private NewsAttachmentMapper newsAttachmentMapper;
    @Resource
    private IOssService ossService;
    @Resource
    private ICacheService cacheService;

    ExternalConfig config = EnvPostProcessor.getExternalConfig();

    private Logger logger = LoggerFactory.getLogger(NewsServiceImpl.class);

    /**后台分页查询新闻列表*/
    public CommonResult list(NewsParam.ListParam param){

        List<News> list = newsMapper.list(param.getStart(), param.getNum(),
                param.getTitle(), param.getState(), param.getType());

        List<String> logicList = newsMapper.newsLogicOrder(0, 7);
        Map<String, Integer> logicMap = new HashMap<>();
        if(logicList!=null && logicList.size()>0){
            for(int i=0; i<logicList.size(); i++){
                logicMap.put(logicList.get(i), i+1);
            }
        }

        List<NewsVo.ListVo> vos = new ArrayList<>();
        for(News news : list){
            NewsVo.ListVo vo = new NewsVo.ListVo();
            vo.setNewsId(news.getId());
            vo.setTitle(news.getTitle());
            vo.setState(news.getState());
            vo.setType(news.getType());
            vo.setCreateTime(TimeUtil.formaterYYYYMMddHHmm(news.getCreateTime()));
            if(news.getPublishTime()==null){
                news.setPublishTime(news.getCreateTime());
            }
            vo.setPublishTime(TimeUtil.formaterYYYYMMddHHmmss(news.getPublishTime()));
            vo.setOrderNum(news.getOrderNum());
            Integer logicOrder = logicMap.get(news.getId());
            if(logicOrder==null){
                vo.setLogicOrder(0);
            }else{
                vo.setLogicOrder(logicOrder);
            }
            vos.add(vo);
        }
        int count = newsMapper.countList(param.getTitle(), param.getState(), param.getType());
        DataGrid<NewsVo.ListVo> dataGrid = new DataGrid<>();
        dataGrid.setRows(vos);
        dataGrid.setTotal(count);
        return Ref.ok(dataGrid);
    }


    /**新增新闻*/
    public CommonResult add(NewsParam.AddParam param){
        //新增新闻时，新闻中的图片，如果是本地上传（不是网络图片）
        //需要去掉新闻图片的本地访问前缀
        String content = removePre(param.getContent());

        Date time = new Date();
        News news = new News();
        news.setTitle(param.getTitle());
        news.setSummary(param.getSummary());
        news.setType(param.getType());
        news.setState(0);
        news.setCreateTime(time);
        news.setUpdateTime(time);
        if(StringUtil.isEmpty(param.getPublishTime())){
            news.setPublishTime(time);
        }else{
            Date date = TimeUtil.parseYYYYMMddHHmmss(param.getPublishTime());
            news.setPublishTime(date);
        }
        news.setOrderNum(param.getOrderNum());

        newsMapper.insert(news);

        NewsContent newsContent = new NewsContent();
        newsContent.setContent(content);
        newsContent.setNewsId(news.getId());
        newsContent.setCreateTime(time);
        newsContent.setUpdateTime(time);
        newsContentMapper.insert(newsContent);
        return Ref.ok();
    }

    /**修改新闻*/
    public CommonResult modify(NewsParam.ModifyParam param){
        News news = newsMapper.selectById(param.getNewsId());
        if(news==null){
            return Ref.error("错误的新闻编号");
        }
        NewsContent newsContent = newsContentMapper.getByNewsId(param.getNewsId());
        if(newsContent==null){
            return Ref.error("错误的新闻编号");
        }
        if(news.getState()!=0 && news.getState()!=1){
            return Ref.error("只有状态为新创建或待修改的新闻才能修改");
        }

        Date time = new Date();
        //修改新闻时，新闻中的图片，如果是本地上传（不是网络图片）
        //需要去掉新闻图片的本地访问前缀
        String content = removePre(param.getContent());

        news.setTitle(param.getTitle());
        news.setSummary(param.getSummary());
        news.setType(param.getType());
        news.setUpdateTime(time);
        newsContent.setContent(content);
        newsContent.setUpdateTime(time);

        if(StringUtil.isEmpty(param.getPublishTime())){
            news.setPublishTime(news.getCreateTime());
        }else{
            Date date = TimeUtil.parseYYYYMMddHHmmss(param.getPublishTime());
            news.setPublishTime(date);
        }
        news.setOrderNum(param.getOrderNum());

        newsMapper.updateById(news);
        newsContentMapper.updateById(newsContent);

        return Ref.ok();
    }

    /**获取新闻详情*/
    public CommonResult get(NewsParam.GetParam param){
        News news = newsMapper.selectById(param.getNewsId());
        if(news==null){
            return Ref.error("错误的新闻编号");
        }
        NewsContent newsContent = newsContentMapper.getByNewsId(param.getNewsId());
        if(newsContent==null){
            return Ref.error("错误的新闻编号");
        }

        NewsVo.GetVo vo = new NewsVo.GetVo();
        vo.setNewsId(news.getId());
        vo.setTitle(news.getTitle());
        vo.setSummary(news.getSummary());
        vo.setOrderNum(news.getOrderNum());
        vo.setType(news.getType());
        vo.setState(news.getState());
        vo.setCreateTime(TimeUtil.convert(news.getCreateTime()));
        vo.setContent(newsContent.getContent());
        return Ref.ok(vo);
    }


    /**发布新闻*/
    public CommonResult publish(NewsParam.PublishParam param){
        News news = newsMapper.selectById(param.getNewsId());
        if(news==null){
            return Ref.error("错误的新闻编号");
        }
        news.setState(1);
        newsMapper.updateById(news);
        cacheService.deleteIndexCache();
        return Ref.ok();
    }

    /**取消发布*/
    public CommonResult cancel(NewsParam.CancelParam param){
        News news = newsMapper.selectById(param.getNewsId());
        if(news==null){
            return Ref.error("错误的新闻编号");
        }
        news.setState(0);
        newsMapper.updateById(news);
        cacheService.deleteIndexCache();
        return Ref.ok();
    }

    /**删除新闻*/
    public CommonResult delete(NewsParam.DeleteParam param){
        News news = newsMapper.selectById(param.getNewsId());
        if(news==null){
            return Ref.error("错误的新闻编号");
        }
        newsMapper.deleteById(param.getNewsId());
        newsContentMapper.deleteByNewsId(param.getNewsId());

        return Ref.ok();
    }

    /**修改序号*/
    public CommonResult commandOrderNum(NewsParam.CommandOrderNumParam param){
        News news = newsMapper.selectById(param.getNewsId());
        if(news==null){
            return Ref.error("错误的新闻编号");
        }
        if(news.getState()==0){
            return Ref.error("未发布的新闻不能在这里修改序号");
        }
        news.setOrderNum(param.getOrderNum());
        newsMapper.updateById(news);
        cacheService.deleteIndexCache();
        return Ref.ok();
    }

    /**新闻详情*/
    public void detail(String newsId){
        News news = newsMapper.selectById(newsId);
        if(news==null){
            return;
        }
        NewsContent newsContent = newsContentMapper.getByNewsId(newsId);
        if(newsContent==null){
            return;
        }
        NewsVo.DetailVo vo = new NewsVo.DetailVo();
        vo.setTitle(news.getTitle());
        vo.setType(news.getType());
        vo.setPublishTime(TimeUtil.formaterYYYYMMdd(news.getPublishTime()));
        vo.setContent(newsContent.getContent());
        HttpServletRequest request = ServletUtil.getRequest();
        request.setAttribute("detail",vo);
    }

    /**前端获取新闻列表*/
    public CommonResult webList(NewsParam.WebListParam param){
        Integer page = param.getPage();
        if(page==null){
            page = 1;
        }
        Integer num = param.getNum();
        if(num==null){
            num = 10;
        }
        int start = (page - 1) * num;
        List<News> newsList = newsMapper.list(start, num, null, 1, param.getType());
        int count = newsMapper.countList(null, 1, param.getType());
        List<NewsVo.WebListVo> vos = new ArrayList<>();
        for(News news : newsList){
            NewsVo.WebListVo vo = new NewsVo.WebListVo();
            vo.setNewsId(news.getId());
            vo.setTitle(news.getTitle());
            vo.setTime(TimeUtil.formaterYYYYMMdd(news.getPublishTime()));
            vos.add(vo);
        }
        DataGrid<NewsVo.WebListVo> dataGrid = new DataGrid<>();
        dataGrid.setRows(vos);
        dataGrid.setTotal(count);
        return Ref.ok(dataGrid);
    }

    /**其他新闻列表*/
    public CommonResult otherList(){
        List<NewsContent> newsContents = newsContentMapper.listOther();
        List<NewsVo.OtherListVo> vos = new ArrayList<>();
        for(NewsContent content : newsContents){
            List<NewsAttachment> newsAttachments = newsAttachmentMapper.listByContentId(content.getId());
            NewsVo.OtherListVo vo = new NewsVo.OtherListVo();
            vo.setContentId(content.getId());
            vo.setAttachCount(newsAttachments.size());
            vo.setCreateTime(TimeUtil.formaterYYYYMMddHHmm(content.getCreateTime()));
            vo.setUpdateTime(TimeUtil.formaterYYYYMMddHHmm(content.getUpdateTime()));
            if(content.getId().equals("xlap")){
                vo.setTitle("线路安排");
            }else if(content.getId().equals("bmch")){
                vo.setTitle("报名参会");
            }else if(content.getId().equals("zzfw")){
                vo.setTitle("增值服务");
            }else if(content.getId().equals("gywm")){
                vo.setTitle("关于我们");
            }else if(content.getId().equals("lxwm")){
                vo.setTitle("联系我们");
            }
            vos.add(vo);
        }
        return Ref.ok(vos);
    }

    /**获取其他新闻的详情*/
    public CommonResult getOther(NewsParam.GetOtherParam param){
        NewsContent content = newsContentMapper.selectById(param.getContentId());
        List<NewsAttachment> newsAttachments = newsAttachmentMapper.listByContentId(content.getId());
        NewsVo.GetOtherVo vo = new NewsVo.GetOtherVo();
        vo.setContent(content.getContent());
        vo.setContentId(content.getId());
        if(newsAttachments!=null && newsAttachments.size()>0){
            for(NewsAttachment attachment : newsAttachments){
                NewsVo.AttachVo attachVo = new NewsVo.AttachVo();
                attachVo.setName(attachment.getName());
                attachVo.setUrl(attachment.getUrl());
                vo.getAttachList().add(attachVo);
            }
        }
        return Ref.ok(vo);
    }


    /**修改其他新闻的详情*/
    public CommonResult modifyOther(NewsParam.ModifyOtherParam param){
        NewsContent content = newsContentMapper.selectById(param.getContentId());
        if(content==null){
            return Ref.error("找不到对应内容");
        }
        String paramContentMd5 = Md5Util.md5(param.getContent());
        String dbContentMd5 = Md5Util.md5(content.getContent());
        // 如果内容不一致，保存
        if(!paramContentMd5.equals(dbContentMd5)){
            content.setContent(param.getContent());
            newsContentMapper.updateById(content);
        }
        // 删除附件，重新保存一次
        newsAttachmentMapper.deleteByContentId(param.getContentId());
        for(int i=0; i<param.getAttachList().size(); i++){
            NewsParam.AttachParam attachParam = param.getAttachList().get(i);
            NewsAttachment attachment = new NewsAttachment();
            attachment.setContentId(param.getContentId());
            attachment.setName(attachParam.getName());
            attachment.setUrl(attachParam.getUrl());
            attachment.setOrderNum(i+1);
            attachment.setCreateTime(new Date());
            newsAttachmentMapper.insert(attachment);
        }
        return Ref.ok();
    }

    /**前端获取新闻列表*/
    public CommonResult pageList(NewsParam.PageListParam param){

        List<News> list = newsMapper.list(param.getStart(), param.getNum(),
                null, 1, param.getType());
        int count = newsMapper.countList(null, 1, param.getType());
        List<NewsVo.PageListVo> vos = new ArrayList<>();
        for(News news : list){
            NewsVo.PageListVo vo = new NewsVo.PageListVo();
            vo.setNewsId(news.getId());
            vo.setTitle(news.getTitle());
            String summary = news.getSummary();
            if(!StringUtil.isEmpty(summary)){
                if(summary.length()>60){
                    summary = summary.substring(0, 60) + "...";
                }
                vo.setSummary(summary);
            }else{
                vo.setSummary("");
            }
            vo.setPublishTime(TimeUtil.formaterYYYYMMdd(news.getPublishTime()));
            vos.add(vo);
        }
        DataGrid<NewsVo.PageListVo> dataGrid = new DataGrid<>();
        dataGrid.setRows(vos);
        dataGrid.setTotal(count);
        return Ref.ok(dataGrid);
    }


    private String removePre(String content){
        String result = content;
        if(!StringUtil.isEmpty(content)){
            Document doc = Jsoup.parse(content);
            Elements imgElements = doc.select("img");
            if(imgElements!=null){
                Iterator<Element> imgIterator = imgElements.iterator();
                while(imgIterator.hasNext()){
                    Element imgElement = imgIterator.next();
                    imgElement.removeAttr("width");
                    imgElement.removeAttr("height");
                    imgElement.removeAttr("style");
                    String src = imgElement.attr("src");
                    String data_src = imgElement.attr("data-src");
                    if (data_src != null && !"".equals(data_src.trim())) {
                        imgElement.removeAttr("src");
                        imgElement.removeAttr("data-src");
                        src = data_src;
                    }
                    String url = imgUploadOss(src);
                    if(StringUtil.isEmpty(url)){
                        imgElement.remove();
                    }else {
                        imgElement.attr("src",url);
                    }
                }
            }
            String docStr = doc.html();
            docStr = docStr.replace("<html>","");
            docStr = docStr.replace("</html>","");
            docStr = docStr.replace("<head>","");
            docStr = docStr.replace("</head>","");
            docStr = docStr.replace("<body>","");
            docStr = docStr.replace("</body>","");
            result = docStr.trim();
        }
        return result;
    }

    // 图片地址上传到oss
    private String imgUploadOss(String src){
        if(StringUtil.isEmpty(src)){
            return "";
        }
        if(src.startsWith(ossService.getPrefix())){
            return src;
        }

        DefaultIdentifierGenerator generator = new DefaultIdentifierGenerator();
        LocalDate now = LocalDate.now();
        int year = now.getYear();
        int month = now.getMonth().getValue();
        StringBuilder builder = new StringBuilder();
        builder.append("news/");
        builder.append(year);
        builder.append("/");
        builder.append(month);
        builder.append("/");
        builder.append(generator.nextId("news"));

        // 本地上传的文件
        if(src.startsWith(config.getEditor().getImgPrefix())){
            src = src.replace(config.getEditor().getImgPrefix(), "");
            File file = new File(config.getEditor().getImgDir());
            String rootFile = "";
            try {
                rootFile = file.getParentFile().getCanonicalPath();
            } catch (IOException e) {
                e.printStackTrace();
            }
            if(StringUtil.isEmpty(rootFile)){
                logger.error("root目录不存在");
                throw new RuntimeException("root目录不存在");
            }
            if(rootFile.endsWith("/")){
                rootFile = rootFile.substring(0, rootFile.length()-1);
            }
            String realFilePath = rootFile + src;
            int i = realFilePath.lastIndexOf(".");
            String fileType = realFilePath.substring(i);
            builder.append(fileType);
            String key = builder.toString();
            return ossService.put(key, realFilePath);

        }
        // 网络图片
        int i = src.lastIndexOf(".");
        String fileType = src.substring(i);
        builder.append(fileType);
        String key = builder.toString();
        return ossService.putUrl(key, src);
    }

    private String addPre(String content){

        String result = content;
//        if(globalParam.getImg().getDev()==0){
//            return result;
//        }
        if(!StringUtil.isEmpty(content)){
            Document doc = Jsoup.parse(content);
            Elements imgElements = doc.select("img");
            if(imgElements!=null){
                Iterator<Element> imgIterator = imgElements.iterator();
                while(imgIterator.hasNext()){
                    Element imgElement = imgIterator.next();
                    String src = imgElement.attr("src");
                    if(src.startsWith("/")){
                        String url = config.getEditor().getImgPrefix() + src;
                        imgElement.removeAttr("src");
                        imgElement.attr("src",url);
                    }
                }
            }
            String docStr = doc.html();
            docStr = docStr.replace("<html>","");
            docStr = docStr.replace("</html>","");
            docStr = docStr.replace("<head>","");
            docStr = docStr.replace("</head>","");
            docStr = docStr.replace("<body>","");
            docStr = docStr.replace("</body>","");
            result = docStr.trim();
        }
        return result;
    }
}
